/*
 * Copyright 2011 Olli Männistö
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.muistikirja;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

import com.muistikirja.R;
import com.muistikirja.NotePad.NoteColumns;

/**
 * Displays a list of notes. Will display notes from the {@link Uri}
 * provided in the intent if there is one, otherwise defaults to displaying the
 * contents of the {@link NoteProvider}
 */
public class NotesList extends ListActivity {
    private static final String TAG = "NotesList";

    /**
     * The columns we are interested in from the database
     */
    private static final String[] PROJECTION = new String[] {
        NoteColumns._ID, // 0
        NoteColumns.NOTE, // 1
        NoteColumns.TITLE, // 2
    };
    /** The index of the note column */
    private static final int COLUMN_INDEX_NOTE = 1;
    /** The index of the title column */
    private static final int COLUMN_INDEX_TITLE = 2;
    
    /** Button to add new note */
    private Button addButton;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);

        // If no data was given in the intent (because we were started
        // as a MAIN activity), then use our default content provider.
        Intent intent = getIntent();
        if (intent.getData() == null) {
            intent.setData(NoteColumns.CONTENT_URI);
        }
        
        // Set addButton properties programmatically.
        addButton = new Button(this);
        addButton.setText(R.string.create_new);
        addButton.setOnClickListener(new OnClickListener() {
        	public void onClick(View v) {
        		startActivity(new Intent(Intent.ACTION_INSERT, 
        				getIntent().getData()));
        		}
        	});
        
        // Settings for ListView.
        getListView().setPadding(5,5,5,5);
        getListView().addHeaderView(addButton);
        getListView().setOnCreateContextMenuListener(this);
        
        // Perform a managed query. The Activity will handle closing and
        // requerying the cursor when needed.
        Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null,
        		null, NoteColumns.CREATED_DATE);

        // Used to map notes entries from the database to views
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, 
        		R.layout.noteslist_item, cursor, 
        		new String[] { NoteColumns.TITLE }, 
        		new int[] { android.R.id.text1 });
        setListAdapter(adapter);
    }

	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate menu from XML resource
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.list_options_menu, menu);
        
        // Generate any additional actions that can be performed on the
        // overall list.  In a normal install, there are no additional
        // actions found here, but this allows other applications to extend
        // our menu with their own actions.
        Intent intent = new Intent(null, getIntent().getData());
        intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
        menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, 
        		new ComponentName(this, NotesList.class), null, intent, 0, 
        		null);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_backup:
            // Try to save backups to sdcard.
        	int errorCount = 0;
        	if (sdCardIsMounted(this)) {
        		Cursor cursor;
        		for (int i = 0; i < getListAdapter().getCount(); i++) {
        			try {
        			cursor = (Cursor) getListAdapter().getItem(i);
        			writeBackupOnSD(java.net.URLEncoder.encode(
        					Integer.toString(i) + "_" + cursor.getString(
        							COLUMN_INDEX_TITLE)) + ".txt", 
        					cursor.getString(COLUMN_INDEX_NOTE));
        			} catch (Exception e) {
        				errorCount++;
        			}
        		}
        		if (errorCount == 0) {
        			Toast.makeText(this, R.string.backup_completed, 
        					Toast.LENGTH_LONG).show();
        		} else {
        			Toast.makeText(this, R.string.backup_failed, 
        					Toast.LENGTH_LONG).show();
        		}
        	} else {
                Toast.makeText(this, R.string.sdcard_failed, 
                		Toast.LENGTH_LONG).show();
        	}
            return true;
        case R.id.menu_about:
            // Show about dialog
        	AlertDialog.Builder builder = new AlertDialog.Builder(this);
        	builder.setIcon(R.drawable.app_notes);
            builder.setTitle(R.string.app_name);
            builder.setMessage(R.string.app_full_name);
            builder.setPositiveButton(R.string.open_browser, 
            		new DialogInterface.OnClickListener() {
            	public void onClick(DialogInterface dialog, int id) {
            		startActivity(new Intent(Intent.ACTION_VIEW, 
            				Uri.parse(getString(R.string.www))));
            		}
            	});
            builder.setNegativeButton(R.string.button_ok, 
            		new DialogInterface.OnClickListener() {
            	public void onClick(DialogInterface dialog, int id) {
            		dialog.dismiss();
            		}
            	});
            builder.show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    public static Boolean sdCardIsMounted(Context mContext){
    	// Check if we can write to sdcard.
        String sdCardStatus = Environment.getExternalStorageState();
        if (sdCardStatus.equals(Environment.MEDIA_MOUNTED)) {
            return true;
        } else if (sdCardStatus.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
            Toast.makeText(mContext, R.string.sdcard_warning, 
            		Toast.LENGTH_LONG).show();
            return true;
        } else {
            return false;
        }
    }
    
    public void writeBackupOnSD(String sFileName, String sBody) {
    	// Write note to file in sdcard.
		try
		{
		    File root = new File(Environment.getExternalStorageDirectory(), 
		    		getString(R.string.app_name));
		    if (!root.exists()) {
		        root.mkdirs();
		    }
		    
		    File date = new File(root,android.text.format.DateFormat.format(
		    		"yyyy_MM_dd", new java.util.Date()).toString());
		    if (!date.exists()) {
		        date.mkdirs();
		    }
		    
		    File bFile = new File(date, sFileName);
		    if (bFile.exists()) {
		    	bFile.delete();
		    }
		    FileWriter writer = new FileWriter(bFile);
		    writer.append(sBody);
		    writer.flush();
		    writer.close();
		}
		catch(IOException e)
		{
			Toast.makeText(this, R.string.backup_failed + e.getMessage(), 
					Toast.LENGTH_LONG).show();
		}
    } 
    
    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, 
    		ContextMenuInfo menuInfo) {
    	AdapterView.AdapterContextMenuInfo info;
        try {
             info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        } catch (ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);
            return;
        }

        Cursor cursor = (Cursor) getListAdapter().getItem(info.position - 1);
        if (cursor == null) {
            // For some reason the requested item isn't available, do nothing.
            return;
        }

        // Inflate menu from XML resource.
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.list_context_menu, menu);
        
        // Set the context menu header.
        menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));
        
        // Append to the
        // menu items for any other activities that can do stuff with it
        // as well.  This does a query on the system for any activities that
        // implement the ALTERNATIVE_ACTION for our data, adding a menu item
        // for each one that is found.
        Intent intent = new Intent(null, 
        		Uri.withAppendedPath(getIntent().getData(),
        				Integer.toString((int) info.id)));
        intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
        menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
        		new ComponentName(this, NotesList.class), null, intent, 0, 
        		null);
    }
    
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info;
        try {
             info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        } catch (ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);
            return false;
        }
        
        Cursor cursor = (Cursor) getListAdapter().getItem(info.position - 1);
        if (cursor == null) {
            // For some reason the requested item isn't available, do nothing.
            return false;
        }
        Uri noteUri = ContentUris.withAppendedId(getIntent().getData(),
        		info.id);
        
        switch (item.getItemId()) {
        case R.id.context_open:
            // Launch activity to edit the currently selected item.
            startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
            return true;
        case R.id.context_delete:
            // Delete the note that the context menu is for.
            getContentResolver().delete(noteUri, null, null);
            return true;
        case R.id.context_send:
            // Launch activity to send the currently selected item.
        	try {
	        	Intent sendIntent = 
	        		new Intent(android.content.Intent.ACTION_SEND);
	        	sendIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
	        			cursor.getString(COLUMN_INDEX_TITLE));
	        	sendIntent.putExtra(android.content.Intent.EXTRA_TEXT,
	        			cursor.getString(COLUMN_INDEX_NOTE));
	        	sendIntent.setType("text/plain");
	        	startActivity(sendIntent);
        	} catch (Exception e) {
        		 Toast.makeText(this,R.string.send_failed,
        				 Toast.LENGTH_SHORT).show();
        	}
        	return true;
        default:
            return super.onContextItemSelected(item);
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), id);
        
        String action = getIntent().getAction();
        if (Intent.ACTION_PICK.equals(action) || 
        		Intent.ACTION_GET_CONTENT.equals(action)) {
            // The caller is waiting for us to return a note selected by
            // the user.  The have clicked on one, so return it now.
            setResult(RESULT_OK, new Intent().setData(noteUri));
        } else {
            // Launch activity to view/edit the currently selected item.
            startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
        }
    }
}
